package ca.cbc.msb.mobilemedia;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Arrays;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ca.cbc.medialib.entity.Media;
import ca.cbc.msb.entity.MSBMessage;
import ca.cbc.msb.util.AppConfig;
import ca.cbc.msb.util.ProgressReport;

import com.yospace.tundra.mediaitemmanagement.CreateMediaItemRequest;
import com.yospace.tundra.mediaitemmanagement.CreateMediaItemResponse;
import com.yospace.tundra.mediaitemmanagement.DeleteMediaItemRequest;
import com.yospace.tundra.mediaitemmanagement.DeleteMediaItemResponse;
import com.yospace.tundra.mediaitemmanagement.MediaItemField;
import com.yospace.tundra.mediaitemmanagement.MediaItemManagement;
import com.yospace.tundra.mediaitemmanagement.MediaItemManagement_Service;
import com.yospace.tundra.mediaitemmanagement.StatusMediaItemRequest;
import com.yospace.tundra.mediaitemmanagement.StatusMediaItemResponse;
import com.yospace.tundra.mediaitemmanagement.UpdateMediaItemFieldsRequest;
import com.yospace.tundra.mediaitemmanagement.UpdateMediaItemFieldsResponse;

/**
 * This class adds the media to Yospace using Yospace's  media api ( Web service
 */

public class YospaceServiceImpl implements MobileMediaService {

	private static Logger log = LoggerFactory.getLogger(YospaceServiceImpl.class);
	private static String YOSPACE_WS_URL = AppConfig.getProperty("yospace.ws.url");
	private static String YOSPACE_USERNAME = AppConfig.getProperty("Username.yospace");
	private static String YOSPACE_PASSWORD = AppConfig.getProperty("Password.yospace");
	private static String YOSPACE_CONTENT_GROUP_ID = AppConfig.getProperty("ContentGroupId.yospace");
    private static String SYNDICATION_BASE_URL = AppConfig.getProperty("syndication.base.url");
    private static String SYNDICATION_USERNAME = AppConfig.getProperty("syndication.username");
    private static String SYNDICATION_PASSWORD = AppConfig.getProperty("syndication.password");
    private static String YOSPACE_CONTENT_PROVIDER_ID = AppConfig.getProperty("ContentProviderId.yospace");
    private static String SYNDICATION_PREFIX;
	private URL yospaceURL;
	
	public YospaceServiceImpl()
	{
	    String strArray[] = SYNDICATION_BASE_URL.split("//");	    
	    SYNDICATION_PREFIX = strArray[0] + "//" + SYNDICATION_USERNAME + ":" + SYNDICATION_PASSWORD + "@" + strArray[1];
		try {
			yospaceURL = new URL(YOSPACE_WS_URL);					
		} catch (MalformedURLException e) {
			throw new RuntimeException("!!!can not create URL for YoSpace web service.", e);
		}		
	}

	private boolean isNullOrEmpty(String str) {
		if(str == null || str.trim().equals(""))
			return true;
		
		return false;
	}
	
	@Override
	public long addMedia(MSBMessage message) {
		log.debug("Adding message ({}) to yospace..", message);
		Media media = message.getMedia();
		
		if(media == null)
			throw new RuntimeException("Media cannot be null there for message (" + message + ")");
		
		MediaItemManagement_Service service = new MediaItemManagement_Service(yospaceURL);
		MediaItemManagement port = service.getMediaItemManagementSOAP();
		CreateMediaItemRequest request = new CreateMediaItemRequest();
		
		request.setUsername(YOSPACE_USERNAME);
		request.setPassword(YOSPACE_PASSWORD);
		request.setContentGroupId(Integer.decode(YOSPACE_CONTENT_GROUP_ID));
		request.setHq(true);
		request.setLargeFormat(true);
		
		/*
		 * Convert cue points to yospace support format
		 * from HH:SS to SSS e,g [2:33, 5:21, 10:21] --> [153, 321, 621]
		 */
		String cuePoints = media.getChapterStartTimes();
		if(!isNullOrEmpty(cuePoints)) {
			String[] cuePointsArray = cuePoints.trim().split("[\\s]*[,;][\\s]*");
			for(int i=0; i<cuePointsArray.length; i++) {
				String[] tmpArray = cuePointsArray[i].split(":");
				int[] hms = {0, 0, 0};
				int k = hms.length;
				for(int j=tmpArray.length-1; j>=0; j--)
					hms[--k] = Integer.valueOf(tmpArray[j]);
				
				cuePointsArray[i] = String.valueOf(hms[0]*60*60 + hms[1]*60 + hms[2]);
			}
			
			cuePoints = Arrays.toString(cuePointsArray);
			request.setCuePoints(cuePoints.substring(1, cuePoints.length()-1));
			
		} else {
			log.warn("!This clip have no cue points...");
		}
		
		// if we update two video with the same name, theP will automaticly add a postfix like __123456, thus will lead getting the wrong filename
		// following will remove possible postfix
		String fileName = media.getOriginalFileName();

		
		//Creating the download url for Yospace. The download base url is e http://syndicationmedia.cbc.ca/mp4/yospace/msb. The file name is the same file name in
        // original url, suffixed with mp4
		request.setContentUrl(SYNDICATION_PREFIX + fileName);
		log.debug("***Url sent to yospace is: {}", request.getContentUrl());
		
		/*
		 * Set geo-fencing metadata here
		 */
		String countries = media.getCountries();
		if(countries != null) {
			MediaItemField metaItem1 = new MediaItemField();
			metaItem1.setFieldName("Restriction Relationship");
			if(media.getExcludeCountries())
				metaItem1.setValue("DENY");
			else
				metaItem1.setValue("ALLOW");
			request.getMetadata().add(metaItem1);	
			
			MediaItemField metaItem2 = new MediaItemField();
			metaItem2.setFieldName("Restriction");
			metaItem2.setValue(countries);
			request.getMetadata().add(metaItem2);		
			
			if(log.isDebugEnabled())
				log.debug(":::Release media with title {} is {} in following countries: " + countries, media.getTitle(), metaItem1.getValue());
		}
		//set the thumbnailURL if there is one
		String thumbnailURL = media.getThumbnailUrl();
		if(!isNullOrEmpty(thumbnailURL))
			request.setThumbnailUrl(thumbnailURL);
		
		String title = media.getTitle();
		if(!isNullOrEmpty(title)) {
			request.setRssTitle(title);	
		}
		
		String description = media.getDescription();
		if(!isNullOrEmpty(description)) {
			request.setRssDescription(description);
		}
		
		/*
		 * Set account, show, season, episode
		 */
		String account = media.getAccount();
		if(!isNullOrEmpty(account)) {
			MediaItemField accountField = new MediaItemField();
			accountField.setFieldName("Account");
			accountField.setValue(account);
			request.getMetadata().add(accountField);	
		}
		
		String show = media.getShow();
		if(!isNullOrEmpty(show)) {
			MediaItemField showField = new MediaItemField();
			showField.setFieldName("Show");
			showField.setValue(show);
			request.getMetadata().add(showField);
		}
		
		String season = media.getSeasonNumber();
		if(!isNullOrEmpty(season)) {
			MediaItemField seasonField = new MediaItemField();
			seasonField.setFieldName("Season");
			seasonField.setValue(season);
			request.getMetadata().add(seasonField);
		}
		
		String episode = media.getEpisodeNumber();
		if(!isNullOrEmpty(episode)) {
			MediaItemField episodeField = new MediaItemField();
			episodeField.setFieldName("Episode");
			episodeField.setValue(episode);
			request.getMetadata().add(episodeField);
		}
		
		CreateMediaItemResponse response = port.createMediaItem(request);
		long yospaceId = (long)(response.getMediaItemId());
		log.debug("Release added to yospace with yospaceId {}..", yospaceId);
		log.debug("Response from adding release is {}..", response.getStatusCode());
		
        media.setMobileId(yospaceId);
        //need commit again for submitting message
        log.info("Message ({}) submitting to YospaceVerificationQueue with yospaceId ({})>>>", message, yospaceId);
        ProgressReport.instance.statusReport(message, " Submitting to Yospace");
		return yospaceId;
	}

	/*
	 * (non-Javadoc)
	 * @see ca.cbc.msb.mobilemedia.MobileMediaService#changeMedia(ca.cbc.msb.shared.MSBMessage)
	 */
	@Override
	public void changeMedia(MSBMessage message) {
		Media media = message.getMedia();
		log.debug("Change message ({}) to yospace...", message);
		MediaItemManagement_Service service = new MediaItemManagement_Service(yospaceURL);
		MediaItemManagement port = service.getMediaItemManagementSOAP();
		UpdateMediaItemFieldsRequest request = new UpdateMediaItemFieldsRequest();	
		request.setUsername(YOSPACE_USERNAME);
		request.setPassword(YOSPACE_PASSWORD);
		request.setGuid(YOSPACE_CONTENT_PROVIDER_ID + "-" + media.getMobileId());
		request.setInputConfigurationId(-1);
		
		log.debug("**************guid is " + request.getGuid());
				
		/*
		 * update geo-fencing metadata here
		 */
		String countries = media.getCountries();
		if(countries != null) {
			MediaItemField metaItem1 = new MediaItemField();
			metaItem1.setFieldName("Restriction Relationship");
			if(media.getExcludeCountries())
				metaItem1.setValue("DENY");
			else
				metaItem1.setValue("ALLOW");
			request.getMediaItemFields().add(metaItem1);	
			
			MediaItemField metaItem2 = new MediaItemField();
			metaItem2.setFieldName("Restriction");
			metaItem2.setValue(countries);
			request.getMediaItemFields().add(metaItem2);		
			
			if(log.isDebugEnabled())
				log.debug(":::Change media with title {} is {} in following countries: " + countries, media.getTitle(), metaItem1.getValue());
		}		
		
		String title = media.getTitle();
		if(!isNullOrEmpty(title)) {
			MediaItemField titleField = new MediaItemField();
			titleField.setFieldName("Title");
			titleField.setValue(title);
			request.getMediaItemFields().add(titleField);
		}
		
		String description = media.getDescription();
		if(!isNullOrEmpty(description)) {
			MediaItemField descriptionField = new MediaItemField();
			descriptionField.setFieldName("Description");
			descriptionField.setValue(description);
			request.getMediaItemFields().add(descriptionField);
		}

		/*
		 * Set account, show, season, episode
		 */
		String account = media.getAccount();
		if(!isNullOrEmpty(account)) {
			MediaItemField accountField = new MediaItemField();
			accountField.setFieldName("Account");
			accountField.setValue(account);
			request.getMediaItemFields().add(accountField);	
		}
		
		String show = media.getShow();
		if(!isNullOrEmpty(show)) {
			MediaItemField showField = new MediaItemField();
			showField.setFieldName("Show");
			showField.setValue(show);
			request.getMediaItemFields().add(showField);
		}
		
		String season = media.getSeasonNumber();
		if(!isNullOrEmpty(season)) {
			MediaItemField seasonField = new MediaItemField();
			seasonField.setFieldName("Season");
			seasonField.setValue(season);
			request.getMediaItemFields().add(seasonField);
		}
		
		String episode = media.getEpisodeNumber();
		if(!isNullOrEmpty(episode)) {
			MediaItemField episodeField = new MediaItemField();
			episodeField.setFieldName("Episode");
			episodeField.setValue(episode);
			request.getMediaItemFields().add(episodeField);
		}

		UpdateMediaItemFieldsResponse response = port.updateMediaItemFields(request);
		
		if(response.getStatusCode() != 200)
			log.error("!!!Error changing from yospace with yospaceId ({})..", message.getMedia().getMobileId());
		log.debug("Change media from YoSpace response: {} with {}", YospaceStatus.lookup(response.getStatusCode()), response.getStatusCode());
	}
	
	@Override
	public void deleteMedia(long yospaceId) {
		MediaItemManagement_Service service = new MediaItemManagement_Service(yospaceURL);
		MediaItemManagement port = service.getMediaItemManagementSOAP();
		DeleteMediaItemRequest request = new DeleteMediaItemRequest();	
		request.setUsername(YOSPACE_USERNAME);
		request.setPassword(YOSPACE_PASSWORD);
		
		request.setMediaItemId((int)yospaceId);
		DeleteMediaItemResponse response = port.deleteMediaItem(request);
		
		if(response.getStatusCode() != 200)
			log.error("!!!Error deleting from yospace with yospaceId ({})..", yospaceId);
		log.debug("Delete media from YoSpace response: {}", YospaceStatus.lookup(response.getStatusCode()));
	}

	@Override
	public YospaceStatus getStatus(long yospaceId) {
		MediaItemManagement_Service service = new MediaItemManagement_Service(yospaceURL);
		MediaItemManagement port = service.getMediaItemManagementSOAP();
		StatusMediaItemRequest request = new StatusMediaItemRequest();
		request.setUsername(YOSPACE_USERNAME);
		request.setPassword(YOSPACE_PASSWORD);
		
		request.setMediaItemId((int)yospaceId);
		StatusMediaItemResponse response = port.statusMediaItem(request);
		
		Integer mediaItemStateCode = response.getMediaItemStateCode();
		if(mediaItemStateCode == null)
			mediaItemStateCode = YospaceStatus.PROCESSING_FAILED.value();
		
		log.debug("yospace status: {}", YospaceStatus.lookup(response.getStatusCode()));
		log.debug("yospaceID: {} yospace media item status: {}", yospaceId, YospaceStatus.lookup(mediaItemStateCode));
		log.debug("yospace item status description: {}", response.getMediaItemStateDescription());
		return YospaceStatus.lookup(mediaItemStateCode);
	}
}
